home *** CD-ROM | disk | FTP | other *** search
- /*
- * STEVIE - ST Editor for VI Enthusiasts ...Tim Thompson...twitch!tjt...
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include "stevie.h"
-
- #ifdef ATARI
- #include <osbind.h>
- #endif
-
- int Rows; /* Number of Rows and Columns */
- int Columns; /* in the current window. */
-
- char *Realscreen; /* What's currently on the screen, a single */
- /* array of size Rows*Columns. */
- char *Nextscreen; /* What's to be put on the screen. */
-
- char *Filename = NULL; /* Current file name */
-
- char *Filemem; /* The contents of the file, as a single array. */
-
- char *Filemax; /* Pointer to the end of allocated space for */
- /* Filemem. (It points to the first byte AFTER */
- /* the allocated space.) */
-
- char *Fileend; /* Pointer to the end of the file in Filemem. */
- /* (It points to the byte AFTER the last byte.) */
-
- char *Topchar; /* Pointer to the byte in Filemem which is */
- /* in the upper left corner of the screen. */
-
- char *Botchar; /* Pointer to the byte in Filemem which is */
- /* just off the bottom of the screen. */
-
- char *Curschar; /* Pointer to byte in Filemem at which the */
- /* cursor is currently placed. */
-
- int Cursrow, Curscol; /* Current position of cursor */
-
- int Cursvcol; /* Current virtual column, the column number of */
- /* the file's actual line, as opposed to the */
- /* column number we're at on the screen. This */
- /* makes a difference on lines that span more */
- /* than one screen line. */
-
- int State = NORMAL; /* This is the current state of the command */
- /* interpreter. */
-
- int Prenum = 0; /* The (optional) number before a command. */
-
- char *Insstart; /* This is where the latest insert/append */
- /* mode started. */
-
- int Changed = 0; /* Set to 1 if something in the file has been */
- /* changed and not written out. */
-
- int Debug = 0;
-
- int Binary = 0; /* Set to 1 if the file should be read and written */
- /* in binary mode (no cr-lf translation). */
-
- char Redobuff[1024]; /* Each command should stuff characters into this */
- /* buffer that will re-execute itself. */
-
- char Undobuff[1024]; /* Each command should stuff characters into this */
- /* buffer that will undo its effects. */
-
- char Insbuff[1024]; /* Each insertion gets stuffed into this buffer. */
-
- char *Uncurschar = NULL;/* Curschar is restored to this before undoing. */
-
- int Ninsert = 0; /* Number of characters in the current insertion. */
- int Undelchars = 0; /* Number of characters to delete, when undoing. */
- char *Insptr = NULL;
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- int mode = 8;
-
- while ( argc>1 && argv[1][0] == '-' ) {
- switch (argv[1][1]) {
- case 'x':
- mode = 16;
- break;
- case 'o':
- mode = 8;
- break;
- case 'd':
- Debug = 1;
- break;
- case 'b':
- Binary = 1;
- break;
- }
- argc--;
- argv++;
- }
-
- if ( argc <= 1 ) {
- fprintf(stderr,"usage: stevie {file}\n");
- exit(1);
- }
-
- Filename = strsave(argv[1]);
-
- windinit();
-
- /* Make sure Rows/Columns are big enough */
- if ( Rows < 3 || Columns < 16 ) {
- fprintf(stderr,"Rows=%d Columns=%d not big enough!\n",
- Rows,Columns);
- windexit(0);
- }
-
- switch ( mode ) {
- case 8:
- octchars();
- break;
- case 16:
- hexchars();
- break;
- }
-
- screenalloc();
- filealloc();
-
- screenclear();
-
- Fileend = Filemem;
- if ( readfile(Filename,Fileend,0) )
- filemess("[New File]");
- Topchar = Curschar = Filemem;
-
- updatescreen();
-
- edit();
-
- windexit(0);
- }
-
- /*
- * filetonext()
- *
- * Based on the current value of Topchar, transfer a screenfull of
- * stuff from Filemem to Nextscreen, and update Botchar.
- */
-
- filetonext()
- {
- int row, col;
- char *screenp = Nextscreen;
- char *memp = Topchar;
- char *endscreen;
- char *nextrow;
- char extra[16];
- int nextra = 0;
- int c;
- int n;
-
- /* The number of rows shown is Rows-1. */
- /* The last line is the status/command line. */
- endscreen = &screenp[(Rows-1)*Columns];
-
- row = col = 0;
- while ( screenp < endscreen && memp < Fileend ) {
-
- /* Get the next character to put on the screen. */
-
- /* The 'extra' array contains the extra stuff that is */
- /* inserted to represent special characters (tabs, and */
- /* other non-printable stuff. The order in the 'extra' */
- /* array is reversed. */
-
- if ( nextra > 0 )
- c = extra[--nextra];
- else {
- c = (unsigned)(0xff & (*memp++));
- /* when getting a character from the file, we */
- /* may have to turn it into something else on */
- /* the way to putting it into 'Nextscreen'. */
- if ( c == '\t' ) {
- strcpy(extra," ");
- /* tab amount depends on current column */
- nextra = (7 - col%8);
- c = ' ';
- }
- else if ( (n=chars[c].ch_size) > 1 ) {
- char *p;
- nextra = 0;
- p = chars[c].ch_str;
- /* copy 'ch-str'ing into 'extra' in reverse */
- while ( n > 1 )
- extra[nextra++] = p[--n];
- c = p[0];
- }
- }
-
- if ( c == '\n' ) {
- row++;
- /* get pointer to start of next row */
- nextrow = &Nextscreen[row*Columns];
- /* blank out the rest of this row */
- while ( screenp != nextrow )
- *screenp++ = ' ';
- col = 0;
- continue;
- }
- /* store the character in Nextscreen */
- if ( col >= Columns ) {
- row++;
- col = 0;
- }
- *screenp++ = c;
- col++;
- }
- /* make sure the rest of the screen is blank */
- while ( screenp < endscreen )
- *screenp++ = ' ';
- /* put '~'s on rows that aren't part of the file. */
- if ( col != 0 )
- row++;
- while ( row < Rows ) {
- Nextscreen[row*Columns] = '~';
- row++;
- }
- Botchar = memp;
- }
-
- /*
- * nexttoscreen
- *
- * Transfer the contents of Nextscreen to the screen, using Realscreen
- * to avoid unnecessary output.
- */
-
- nexttoscreen()
- {
- char *np = Nextscreen;
- char *rp = Realscreen;
- char *endscreen;
- char nc;
- int row = 0, col = 0;
- int gorow = -1, gocol = -1;
-
- endscreen = &np[(Rows-1)*Columns];
-
- for ( ; np < endscreen ; np++,rp++ ) {
- /* If desired screen (contents of Nextscreen) does not */
- /* match what's really there, put it there. */
- if ( (nc=(*np)) != (*rp) ) {
- *rp = nc;
- /* if we are positioned at the right place, */
- /* we don't have to use windgoto(). */
- if ( ! (gorow == row && gocol == col) )
- windgoto(gorow=row,gocol=col);
- windputc(nc);
- gocol++;
- }
- if ( ++col >= Columns ) {
- col = 0;
- row++;
- }
- }
- windrefresh();
- }
-
- updatescreen()
- {
- filetonext();
- nexttoscreen();
- }
-
- screenclear()
- {
- int n;
-
- windclear();
- /* blank out the stored screens */
- for ( n=Rows*Columns-1; n>=0; n-- ) {
- Realscreen[n] = ' ';
- Nextscreen[n] = ' ';
- }
- }
-
- filealloc()
- {
- if ( (Filemem=malloc((unsigned)FILELENG)) == NULL ) {
- fprintf(stderr,"Unable to allocate %d bytes for file memory!\n",
- FILELENG);
- exit(1);
- }
- Filemax = Filemem + FILELENG;
- }
-
- screenalloc()
- {
- Realscreen = malloc((unsigned)(Rows*Columns));
- Nextscreen = malloc((unsigned)(Rows*Columns));
- }
-
- readfile(fname,fromp,nochangename)
- char *fname;
- char *fromp;
- int nochangename; /* if 1, don't change the Filename */
- {
- #ifdef ATARI
- static char currdisk = 0;
- char fbuff[128];
- int c1, c2;
- #endif
- FILE *f;
- char buff[128];
- char *p;
- int c, n;
- int unprint = 0;
-
- #ifdef ATARI
- if ( currdisk == 0 )
- currdisk = 'a' + Dgetdrv();
-
- /* If a drive is specified, it is used from then */
- /* on as the default drive. */
- c1 = tolower(*fname);
- c2 = *(fname+1);
- if ( c2 == ':' && c1>='a' && c1<='z' )
- currdisk = c1;
- else {
- /* if no drive is specified, use the default one. */
- sprintf(fbuff,"%c:%s",toupper(currdisk),fname);
- fname = fbuff;
- }
- #endif
- if ( ! nochangename )
- Filename = strsave(fname);
-
- #ifdef ATARI
- if ( (f=fopen(fname,Binary?"br":"r")) == NULL ) {
- #else
- if ( (f=fopen(fname,"r")) == NULL ) {
- #endif
- Fileend = Filemem;
- return(1);
- }
-
- for ( n=0; (c=getc(f)) != EOF; n++ ) {
- if ( ! (isprint(c)||isspace(c)) )
- unprint++;
- if ( fromp >= Filemax ) {
- fprintf(stderr,"File too long (limit is %d)!\n",FILELENG);
- exit(1);
- }
- /* Insert the char at the current point by shifting
- /* everything down. */
- for ( p=Fileend; p>fromp; p-- )
- *p = *(p-1);
- *fromp++ = c;
- if ( Fileend < fromp )
- Fileend = fromp;
- }
- if ( ! Binary && unprint > 0 ) {
- sprintf(buff,"%d unprintable chars! Perhaps binary mode (-b) should be used?",unprint);
- message(buff);
- sleep(2);
- }
- if ( unprint > 0 )
- p = "\"%s\" %d characters (%d un-printable) (Press 'H' for help)";
- else
- p = "\"%s\" %d characters (Press 'H' for help)";
- sprintf(buff,p,fname,n,unprint);
- message(buff);
- fclose(f);
- return(0);
- }
-
- static char getcbuff[1024];
- static char *getcnext = NULL;
-
- stuffin(s)
- char *s;
- {
- if ( getcnext == NULL ) {
- strcpy(getcbuff,s);
- getcnext = getcbuff;
- }
- else
- strcat(getcbuff,s);
- }
-
- addtobuff(s,c1,c2,c3,c4,c5,c6)
- char *s;
- char c1, c2, c3, c4, c5, c6;
- {
- char *p = s;
- if ( (*p++ = c1) == '\0' )
- return;
- if ( (*p++ = c2) == '\0' )
- return;
- if ( (*p++ = c3) == '\0' )
- return;
- if ( (*p++ = c4) == '\0' )
- return;
- if ( (*p++ = c5) == '\0' )
- return;
- if ( (*p++ = c6) == '\0' )
- return;
- }
-
- vgetc()
- {
- if ( getcnext != NULL ) {
- int nextc = *getcnext++;
- if ( *getcnext == '\0' ) {
- *getcbuff = '\0';
- getcnext = NULL;
- }
- return(nextc);
- }
- return(windgetc());
- }
-
- vpeekc()
- {
- if ( getcnext != NULL )
- return(*getcnext);
- return(-1);
- }
-
- /*
- * anyinput
- *
- * Return non-zero if input is pending.
- */
-
- anyinput()
- {
- if ( getcnext != NULL )
- return(1);
- return(0);
- }
-
- #ifdef ATARI
- sleep(n)
- int n;
- {
- int k;
-
- k = Tgettime();
- while ( Tgettime() <= k+n )
- ;
- }
- #endif
-